package de.hhkk.util;

import java.util.Calendar;

import org.eclipse.core.databinding.observable.Diffs;
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
import org.eclipse.nebula.widgets.calendarcombo.CalendarCombo;
import org.eclipse.nebula.widgets.calendarcombo.ICalendarListener;

public class CalendarComboObservableValue extends AbstractObservableValue
{

    /**
     * The Control being observed here.
     */
    protected final CalendarCombo cc;

    /**
     * Flag to prevent infinite recursion in {@link #doSetValue(Object)}.
     */
    protected boolean             updating = false;

    /**
     * The "old" selection before a selection event is fired.
     */
    protected Calendar            currentDate;

    private ICalendarListener     listener = new ICalendarListener()
                                           {

                                               @Override
                                               public void popupClosed()
                                               {
                                                   // SKIP
                                               }

                                               @Override
                                               public void dateRangeChanged(Calendar arg0, Calendar arg1)
                                               {
                                                   if (!updating)
                                                   {
                                                       Calendar newDate = CalendarComboObservableValue.this.cc
                                                               .getDate();
                                                       fireValueChange(Diffs.createValueDiff(currentDate, newDate));
                                                       currentDate = newDate;
                                                   }
                                               }

                                               @Override
                                               public void dateChanged(Calendar arg0)
                                               {
                                                   if (!updating)
                                                   {
                                                       Calendar newDate = CalendarComboObservableValue.this.cc
                                                               .getDate();
                                                       fireValueChange(Diffs.createValueDiff(currentDate, newDate));
                                                       currentDate = newDate;
                                                   }
                                               }
                                           };

    /**
     * Observe the selection property of the provided CalendarCombo control.
     * @param cc the control to observe
     */
    public CalendarComboObservableValue(CalendarCombo cc)
    {
        this.cc = cc;
        currentDate = cc.getDate();
        this.cc.addCalendarListener(listener);
    }

    @Override
    public synchronized void dispose()
    {
        cc.removeCalendarListener(listener);
        super.dispose();
    }

    protected Object doGetValue()
    {
        if (!cc.isDisposed())
        {
            return cc.getDate();
        }
        return null;
    }

    protected void doSetValue(Object value)
    {
        if (value instanceof Calendar && !cc.isDisposed())
        {
            Calendar oldValue;
            Calendar newValue;
            try
            {
                updating = true;
                oldValue = cc.getDate();
                newValue = (Calendar) value;
                cc.setDate(newValue);
                currentDate = newValue;
                fireValueChange(Diffs.createValueDiff(oldValue, newValue));
            }
            finally
            {
                updating = false;
            }
        }
    }

    public Object getValueType()
    {
        return Calendar.class;
    }
}
